using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CollabApp.Domain.Entities.Room;

/// <summary>
/// 房间玩家实体 - 记录玩家在房间中的状态和信息
/// </summary>
[Table("room_players")]
public class RoomPlayer : BaseEntity
{
    /// <summary>
    /// 关联房间ID - 外键，指向Rooms表
    /// </summary>
    [Required]
    [Column("room_id")]
    public Guid RoomId { get; private set; }

    /// <summary>
    /// 关联用户ID - 外键，指向Users表
    /// </summary>
    [Required]
    [Column("user_id")]
    public Guid UserId { get; private set; }

    /// <summary>
    /// 是否准备就绪 - 玩家是否已准备开始游戏
    /// </summary>
    [Column("is_ready")]
    public bool IsReady { get; private set; } = false;

    /// <summary>
    /// 加入顺序 - 玩家加入房间的先后顺序，可用于分配颜色等
    /// </summary>
    [Column("join_order")]
    public int? JoinOrder { get; private set; }

    /// <summary>
    /// 玩家颜色 - 十六进制颜色代码，用于游戏中区分不同玩家
    /// </summary>
    [MaxLength(7)]
    [Column("player_color")]
    public string? PlayerColor { get; private set; }

    // ============ 构造函数 ============

    /// <summary>
    /// 无参构造函数 - EF Core 必需
    /// </summary>
    private RoomPlayer() { }

    /// <summary>
    /// 私有构造函数 - 仅限工厂方法调用
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="joinOrder">加入顺序</param>
    /// <param name="playerColor">玩家颜色</param>
    private RoomPlayer(Guid roomId, Guid userId, int? joinOrder = null, string? playerColor = null)
    {
        RoomId = roomId;
        UserId = userId;
        IsReady = false;
        JoinOrder = joinOrder;
        PlayerColor = playerColor;
    }

    // ============ 导航属性 ============
    
    /// <summary>
    /// 关联的房间实体 - 多对一关系
    /// </summary>
    [ForeignKey("RoomId")]
    public virtual Room Room { get; set; } = null!;
    
    /// <summary>
    /// 关联的用户实体 - 多对一关系
    /// </summary>
    [ForeignKey("UserId")]
    public virtual Auth.User User { get; set; } = null!;

    // ============ 工厂方法 ============

    /// <summary>
    /// 创建新的房间玩家记录 - 工厂方法
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="joinOrder">加入顺序</param>
    /// <param name="playerColor">玩家颜色</param>
    /// <returns>新的房间玩家实例</returns>
    public static RoomPlayer CreateRoomPlayer(Guid roomId, Guid userId, int? joinOrder = null, string? playerColor = null)
    {
        if (roomId == Guid.Empty)
            throw new ArgumentException("房间ID不能为空", nameof(roomId));
        if (userId == Guid.Empty)
            throw new ArgumentException("用户ID不能为空", nameof(userId));

        return new RoomPlayer(roomId, userId, joinOrder, playerColor);
    }

    // ============ 业务方法 ============

    /// <summary>
    /// 设置准备状态
    /// </summary>
    /// <param name="isReady">是否准备</param>
    public void SetReady(bool isReady)
    {
        IsReady = isReady;
    }

    /// <summary>
    /// 切换准备状态
    /// </summary>
    public void ToggleReady()
    {
        IsReady = !IsReady;
    }

    /// <summary>
    /// 设置加入顺序
    /// </summary>
    /// <param name="order">加入顺序</param>
    public void SetJoinOrder(int order)
    {
        if (order < 1)
            throw new ArgumentException("加入顺序必须大于0", nameof(order));

        JoinOrder = order;
    }

    /// <summary>
    /// 设置玩家颜色
    /// </summary>
    /// <param name="color">十六进制颜色代码（如：#FF0000）</param>
    public void SetPlayerColor(string? color)
    {
        if (color != null && !IsValidHexColor(color))
            throw new ArgumentException("无效的颜色格式，请使用十六进制格式（如：#FF0000）", nameof(color));

        PlayerColor = color;
    }

    /// <summary>
    /// 验证十六进制颜色格式
    /// </summary>
    /// <param name="color">颜色代码</param>
    /// <returns>是否为有效格式</returns>
    private static bool IsValidHexColor(string color)
    {
        if (string.IsNullOrWhiteSpace(color))
            return false;

        // 必须以#开头，后跟6位十六进制字符
        if (color.Length != 7 || color[0] != '#')
            return false;

        for (int i = 1; i < 7; i++)
        {
            char c = color[i];
            if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')))
                return false;
        }

        return true;
    }
}
